"""
权限继承服务 - 处理权限层级关系和继承逻辑
"""

from typing import List, Dict, Set
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, and_
from sqlalchemy.orm import selectinload

from app.models.auth import Permission, User
from app.core.logger import logger


class PermissionHierarchyService:
    """权限继承服务"""
    
    def __init__(self):
        # 权限继承关系缓存
        self._hierarchy_cache: Dict[str, Set[str]] = {}
        self._cache_loaded = False
    
    async def load_hierarchy_cache(self, db: AsyncSession) -> None:
        """加载权限继承关系到缓存"""
        try:
            # 查询所有权限继承关系
            from app.models.auth import PermissionHierarchy
            
            stmt = select(PermissionHierarchy).options(
                selectinload(PermissionHierarchy.parent_permission),
                selectinload(PermissionHierarchy.child_permission)
            )
            result = await db.execute(stmt)
            hierarchies = result.scalars().all()
            
            # 构建继承关系映射
            self._hierarchy_cache.clear()
            for hierarchy in hierarchies:
                parent_name = hierarchy.parent_permission.name
                child_name = hierarchy.child_permission.name
                
                if parent_name not in self._hierarchy_cache:
                    self._hierarchy_cache[parent_name] = set()
                self._hierarchy_cache[parent_name].add(child_name)
            
            self._cache_loaded = True
            logger.info(f"权限继承关系缓存加载完成，共 {len(self._hierarchy_cache)} 个父权限")
            
        except Exception as e:
            logger.error(f"加载权限继承关系失败: {e}")
            self._hierarchy_cache.clear()
            self._cache_loaded = False
    
    async def get_expanded_permissions(
        self, 
        db: AsyncSession, 
        permission_names: List[str]
    ) -> List[str]:
        """展开权限列表，包含所有继承的子权限"""
        if not self._cache_loaded:
            await self.load_hierarchy_cache(db)
        
        expanded = set(permission_names)
        
        def expand_permission(perm_name: str):
            """递归展开单个权限"""
            if perm_name in self._hierarchy_cache:
                for child_perm in self._hierarchy_cache[perm_name]:
                    if child_perm not in expanded:
                        expanded.add(child_perm)
                        expand_permission(child_perm)  # 递归展开子权限
        
        # 展开所有权限
        for perm_name in permission_names:
            expand_permission(perm_name)
        
        return list(expanded)
    
    async def get_user_effective_permissions(
        self,
        db: AsyncSession,
        user: User
    ) -> List[str]:
        """获取用户的所有有效权限（包括继承的）"""
        try:
            # 重新查询用户以确保关联数据完整加载
            from app.models.auth import UserRole, Role, RolePermission
            from sqlalchemy import select
            from sqlalchemy.orm import selectinload

            stmt = select(User).where(User.id == user.id).options(
                selectinload(User.user_roles).selectinload(UserRole.role).selectinload(Role.role_permissions).selectinload(RolePermission.permission)
            )
            result = await db.execute(stmt)
            user_with_permissions = result.scalar_one_or_none()

            if not user_with_permissions:
                logger.warning(f"用户 {user.username} 不存在")
                return []

            # 获取用户的直接权限
            user_permissions = [p.name for p in user_with_permissions.get_permissions()]

            # 展开权限继承
            effective_permissions = await self.get_expanded_permissions(db, user_permissions)

            logger.debug(f"用户 {user.username} 的直接权限: {user_permissions}")
            logger.debug(f"用户 {user.username} 的有效权限: {len(effective_permissions)} 个")
            return effective_permissions

        except Exception as e:
            logger.error(f"获取用户有效权限失败: {e}")
            return []
    
    async def check_permission(
        self, 
        db: AsyncSession, 
        user: User, 
        required_permission: str
    ) -> bool:
        """检查用户是否拥有指定权限（包括继承的）"""
        try:
            # 超级用户拥有所有权限
            if user.is_superuser:
                return True
            
            # 获取用户的有效权限
            effective_permissions = await self.get_user_effective_permissions(db, user)
            
            return required_permission in effective_permissions
            
        except Exception as e:
            logger.error(f"权限检查失败: {e}")
            return False
    
    async def check_any_permission(
        self, 
        db: AsyncSession, 
        user: User, 
        required_permissions: List[str]
    ) -> bool:
        """检查用户是否拥有任一指定权限"""
        try:
            if user.is_superuser:
                return True
            
            effective_permissions = await self.get_user_effective_permissions(db, user)
            
            return any(perm in effective_permissions for perm in required_permissions)
            
        except Exception as e:
            logger.error(f"权限检查失败: {e}")
            return False
    
    async def check_all_permissions(
        self, 
        db: AsyncSession, 
        user: User, 
        required_permissions: List[str]
    ) -> bool:
        """检查用户是否拥有所有指定权限"""
        try:
            if user.is_superuser:
                return True
            
            effective_permissions = await self.get_user_effective_permissions(db, user)
            
            return all(perm in effective_permissions for perm in required_permissions)
            
        except Exception as e:
            logger.error(f"权限检查失败: {e}")
            return False
    
    async def can_perform_action(
        self, 
        db: AsyncSession, 
        user: User, 
        resource: str, 
        action: str
    ) -> bool:
        """检查用户是否能对指定资源执行指定操作"""
        permission_name = f"{resource}.{action}"
        return await self.check_permission(db, user, permission_name)
    
    async def get_user_available_actions(
        self, 
        db: AsyncSession, 
        user: User, 
        resource: str
    ) -> List[str]:
        """获取用户对指定资源的可用操作"""
        try:
            effective_permissions = await self.get_user_effective_permissions(db, user)
            
            # 过滤出指定资源的权限
            resource_permissions = [
                perm for perm in effective_permissions 
                if perm.startswith(f"{resource}.")
            ]
            
            # 提取操作名称
            actions = [perm.split('.', 1)[1] for perm in resource_permissions]
            
            return list(set(actions))  # 去重
            
        except Exception as e:
            logger.error(f"获取用户可用操作失败: {e}")
            return []
    
    async def get_permission_children(
        self, 
        db: AsyncSession, 
        permission_name: str
    ) -> List[str]:
        """获取指定权限的所有子权限"""
        if not self._cache_loaded:
            await self.load_hierarchy_cache(db)
        
        return list(self._hierarchy_cache.get(permission_name, set()))
    
    async def refresh_cache(self, db: AsyncSession) -> None:
        """刷新权限继承关系缓存"""
        self._cache_loaded = False
        await self.load_hierarchy_cache(db)
    
    def get_hierarchy_info(self) -> Dict[str, List[str]]:
        """获取权限继承关系信息（用于调试）"""
        return {
            parent: list(children) 
            for parent, children in self._hierarchy_cache.items()
        }


# 创建全局权限继承服务实例
permission_hierarchy_service = PermissionHierarchyService()


# 权限检查装饰器工厂
def require_permission_with_hierarchy(permission: str):
    """基于权限继承的权限检查装饰器"""
    from fastapi import Depends, HTTPException, status
    from app.core.database import get_db
    from app.core.dependencies import get_current_active_user
    
    async def permission_checker(
        current_user: User = Depends(get_current_active_user),
        db: AsyncSession = Depends(get_db)
    ) -> User:
        has_permission = await permission_hierarchy_service.check_permission(
            db, current_user, permission
        )
        
        if not has_permission:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail=f"需要权限: {permission}"
            )
        
        return current_user
    
    return permission_checker


def require_any_permission_with_hierarchy(permissions: List[str]):
    """基于权限继承的任一权限检查装饰器"""
    from fastapi import Depends, HTTPException, status
    from app.core.database import get_db
    from app.core.dependencies import get_current_active_user
    
    async def permission_checker(
        current_user: User = Depends(get_current_active_user),
        db: AsyncSession = Depends(get_db)
    ) -> User:
        has_permission = await permission_hierarchy_service.check_any_permission(
            db, current_user, permissions
        )
        
        if not has_permission:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail=f"需要以下权限之一: {', '.join(permissions)}"
            )
        
        return current_user
    
    return permission_checker


def require_resource_action(resource: str, action: str):
    """基于资源-操作的权限检查装饰器"""
    from fastapi import Depends, HTTPException, status
    from app.core.database import get_db
    from app.core.dependencies import get_current_active_user
    
    async def permission_checker(
        current_user: User = Depends(get_current_active_user),
        db: AsyncSession = Depends(get_db)
    ) -> User:
        can_perform = await permission_hierarchy_service.can_perform_action(
            db, current_user, resource, action
        )
        
        if not can_perform:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail=f"需要权限: {resource}.{action}"
            )
        
        return current_user
    
    return permission_checker
